

// contructor
dbg.DraggableList = function(listEl, url) {
	//$log('DraggableList constructor listEl='+listEl+' url='+url);
	// PROPS
	this.list = jQuery(listEl);
	this.listEl = listEl;
	this.listName = listEl.id;
	
	this.url = url;
	
	this.sending = false;
	this.enabled = true;
	this.history = [];
	
	this.dragIndex = null;
	this.dropIndex = null;
	this.tmpIndex = null;
	
	// METHODS
	this.initHandler = function(index, handler) {
		//$log(this+'.initHandler index='+index+' handler='+handler);
		var dataObj = {
			handler:handler
		};
		//handler = jQuery(handler);
		if (dbg.DraggableList.useDblClick) {
			//handler.bind('dblclick', dataObj, $d(this, 'dblclick'));
		}
		//handler.bind('mousedown', dataObj, $d(this, 'drag'));
		handler.onmousedown = $d(this, 'drag', dataObj);
	};
		
	//
	this.toString = function() {
		return dbg.DraggableList+'_'+this.listName;
	};
	
	// sorting
	//this.drag = function(event, data) {
	this.drag = function(data, event) {
		//$log(this+'.drag');
		if (this.enabled) {
			event = window.event || event;
			event.data = data;
			this.dragIndex = 
			this.dropIndex = 
			this.tmpIndex = this.getHandlerIndex(event.data.handler);
			var row = this.getRow(this.tmpIndex);
			row.addClass(dbg.DraggableList.draggedClass);
			var handler = jQuery(event.data.handler);
			event.data.mousemove = $d(this, 'move', event.data);
			event.data.mouseup = $d(this, 'drop', event.data);
			event.data.selectstart = $d(this, function() { return false; }, event.data);
			//jQuery(document).bind('mousemove', event.data, event.data.mousemove);
			//jQuery(document).bind('mouseup', event.data, event.data.mouseup);
			//jQuery(document).bind('selectstart', event.data.selectstart);
			this.mouseMoveId = dbg.Events.addEvent('document', 'onmousemove', $d(this, 'move', event.data));
			this.mouseUpId = dbg.Events.addEvent('document', 'onmouseup', $d(this, 'drop', event.data));
			//this.selectStartId = dbg.Events.addEvent('document', 'onselectstart', function() { return false; });
			document.onselectstart = function() {
				return false;
			}
		}
		return false;
	};
	//this.drop = function(event, data) {
	this.drop = function(data, event) {
		//$log(this+'.drop');
		event = window.event || event;
		event.data = data;
		if (this.tmpIndex != this.dragIndex) {
			this.dropIndex = this.tmpIndex;
			this.update();
		}
		var row = this.getRow(this.dropIndex);
		row.removeClass(dbg.DraggableList.draggedClass);
		
		var handler = jQuery(event.data.handler);
		//jQuery(document).unbind('mousemove', event.data.mousemove);
		//jQuery(document).unbind('mouseup', event.data.mouseup);
		//jQuery(document).unbind('selectstart', event.data.selectstart);
		dbg.Events.removeEvent('document', 'onmousemove', this.mouseMoveId);
		dbg.Events.removeEvent('document', 'onmouseup', this.mouseUpId);
		//dbg.Events.removeEvent('document', 'onselectstart', this.selectStartId);
		document.onselectstart = null;
	};
	this.move = function(data, event) {
		//$log(this+'.move');
		event = window.event || event;
		event.data = data;
		if (this.timeout !== null) {
			clearTimeout(this.timeout);
		}
		var mEvent = new dbg.MouseEvent(event);
		var rows = this.getRows();
		var rowsCount = rows.length;
		var row = rows.eq(0);
		var rowsY = row.offset().top;
		var rowH = row.height();
		//var row = rows[0];
		//var rowsY = util.getElementY(row);
		//var rowH = util.getElementHeight(row);
		var index, y;
		for (var i = 0; i < rowsCount; i++) {
			y = rowsY+rowH*i;
			if (i === 0 && y > mEvent.y) {
				index = 0;
				break;
			} else if ((y < mEvent.y && y+rowH > mEvent.y) || i >= rowsCount-1) {
				index = i;
				break;
			}
		}
		if (index != this.tmpIndex) {
			//this.timeout = setTimeout($d(this, 'changePosition', this.tmpIndex, index), 10);
			$d(this, 'changePosition', this.tmpIndex, index)();
		}
	};
	this.dblclick = function(data, event) {
		//$log(this+'.dblclick');
		event = window.event || event;
		event.data = data;
		var dataObj = {
			handler:event.data.handler
		};
		var handler = jQuery(event.data.handler);
		handler.unbind('dblclick');
		handler.bind('keydown', event.data, $d(this, 'keydown'));
		var value = handler.html();
		handler.html('<input type="text" value="'+value+'" /><span class="hidden">'+value+'</span>');
		handler.find('input').bind('blur', dataObj, $d(this, 'blur')).focus();
	};
	this.blur = function(data, event) {
		//$log(this+'.blur');
		event = window.event || event;
		event.data = data;
		var handler = jQuery(event.data.handler);
		handler.unbind('keydown');
		var input = handler.find('input');
		handler.find('input').unbind('blur');
		handler.html(handler.find('input').attr('value'));
	};
	this.keydown = function(data, event) {
		//$log(this+'.keydown');
		event = window.event || event;
		event.data = data;
		switch (event.keyCode) {
			case dbg.Keyboard.ENTER:
				this.update(event);
				break;
			case dbg.Keyboard.ESCAPE:
				this.update(event);
				break;
		}
	};
	
	// data
	this.update = function() {
		//$log(this+'.update');
		this.sending = true;
		this.enabled = false;
		this.history.push();
		
		//this.handlers = jQuery(listEl).find(dbg.DraggableList.handlerSelector);
		
		var props = {
			list:this.listName,
			id:this.getRow(this.dropIndex).attr('id')
		};
		if (this.dropIndex > 0) {
			props.after = this.getRow(this.dropIndex-1).attr('id');
		}
		if (this.dropIndex < this.handlers.length-1) {
			props.before = this.getRow(this.dropIndex+1).attr('id');
		}
		
		this.ajax.post(this.url || dbg.DraggableList.url, props, $d(this, 'success'), $d(this, 'error'));
	};
	this.cancel = function() {
		//$log(this+'.cancel');
		this.ajax.cancel();
		this.sending = false;
		this.undo();
	};
	this.success = function(data) {
		//$log(this+'.success');
		if (this.sending) {
			this.sending = false;
			this.updatePositions();
			this.enabled = true;
		}
		
		eval(data.responseText);
		
		if (response.returnStatus == "0") {
			alert(response.errorMessage);
			window.location.reload();
		}
	};
	this.error = function() {
		//$log(this+'.error');
		if (this.sending) {
			alert('Грешка при изпращането за заявката!');
			this.undo();
			this.sending = false;
			this.enabled = true;
		}
	};
	
	// UTILS
	this.changePosition = function(from, to) {
		//$log(this+'.changePosition from='+from+' to='+to);
		var rows = this.getRows();
		if ((from >= 0 && from < rows.length) && (to >= 0 && to < rows.length)) {
			var $to = jQuery(rows[to]);
			var $from = jQuery(rows[from]);
			var row = $from.remove();
			if (to < rows.length-1) {
				if (from > to) {
					$to.before(row);
				} else {
					$to.after(row);
				}
			} else {
				$to.after(row);
			}
		} else {
			//$log('ERROR: Bad indexes!');
		}
		this.tmpIndex = to;
	};
	this.updatePositions = function() {
		//$log('updatePositions');
		this.handlers = jQuery(listEl).find(dbg.DraggableList.handlerSelector);
		var handlersCount = this.handlers.length;
		//$log('handlersCount='+handlersCount);
		var num, minNum = 0;
		for (var i = 0; i < handlersCount; i++) {
			num = Number(this.handlers[i].innerHTML);
			minNum = Math.min(num, !i ? num : minNum);
		}
		for (i = 0; i < handlersCount; i++) {
			this.handlers[i].innerHTML = minNum+i;
		}
	};
	this.undo = function() {
		//$log(this+'.undo');
		if (this.sending) {
			this.ajax.cancel();
		}
		this.changePosition(this.dropIndex, this.dragIndex);
	};
	this.getRows = function(index) {
		//$log('getRows index='+index);
		return this.list.find(dbg.DraggableList.rowSelector+(!isNaN(index) ? ':eq('+index+')' : ''));
	};
	this.getRow = function(index) {
		//$log('getRow index='+index);
		return this.getRows(index);
	};
	this.getHandlerIndex = function(handler) {
		//$log('getHandlerIndex handler='+handler);
		var rows = this.getRows();
		var len = rows.length;
		for (var i = 0; i < len; i++) {
			if (jQuery(rows[i]).find(dbg.DraggableList.handlerSelector)[0] == handler) {
				return i;
			}
		}
		//$log('ERROR: handler position not found; handler='+handler);
	};
	
	// INIT
	// ajax
	this.ajax = new dbg.Ajax();
	// handlers
	this.handlers = jQuery(listEl).find(dbg.DraggableList.handlerSelector);
	//$log('handlers='+this.handlers.length);
	this.handlers.each($d(this, 'initHandler'));
};

// PUBLIC STATIC METHODS
dbg.DraggableList.init = function(list) {
	//$log(this+'.init list='+list);
	if (list) {
		this.initList(null, list);
	} else {
		jQuery(this.listSelector).each($d(this, 'initList'));
	}
};
dbg.DraggableList.initList = function(index, list, url) {
	//$log(this+'.initList index='+index+' list='+list+' url='+url);
	//list = typeof(index) === 'number' ? list : index;
	//$log('list='+list+' id='+list.id);
	if (list) {
		var listObj = new dbg.DraggableList(list, url);
	}
};
dbg.DraggableList.toString = function() {
	return this.className;
};

// PUBLIC STATIC PROPS
dbg.DraggableList.listSelector = '.draggable_list';
dbg.DraggableList.rowSelector = '.draggable';
dbg.DraggableList.handlerSelector = '.drag';
dbg.DraggableList.draggedClass = 'dragged';
dbg.DraggableList.url = 'admin/index/reorder';
dbg.DraggableList.maxHistory = 10;
dbg.DraggableList.useDblClick = false;

// PRIVATE STATIC PROPS
dbg.DraggableList.className = 'dbg.DraggableList';

jQuery(document).ready(function() { dbg.DraggableList.init(); });

/* use with another url
<script type="text/javascript">
	dbg.DraggableList.initList(null, jQuery('#draggable_list_id'), 'admin/articles/reorder');
</script>
*/